/******************************************************************************
 * * calc_main.c - implementation of calculator main functions
 *
 * *(C) Copyright 2019 Asr International Ltd.
 * * All Rights Reserved
 * ******************************************************************************/

/*********************
*      INCLUDES
*********************/
#include "calc_global.h"
#include "ui_global.h"
#include "ui_log.h"

/*********************
*      DEFINES
*********************/
#define CALC_LATIN_SYMBOL_MUL_AND_DIV_SUP  0

LV_IMG_DECLARE(calculator);

typedef struct
{
    INT8 *Fac1;
    INT8 *Fac2;
    INT8 *Oper1;
    INT8 *Oper2;
    INT8 *Res;
} Calc_Operate_State;

/**********************
*  STATIC VARIABLES
**********************/
static VOID               *gp_CalcCurUIDesc = NULL;
static BOOL               Flag              = FALSE;
static BOOL               LongPressClear    = FALSE;
static TIMER_ID           TimeId            = NULL;
static Calc_Operate_State gs_CalcOperState;

/**********************
*      MACROS
**********************/
#define CALC_MAX_RESULT_LEN (FP_CALULATOR_TA_MAX_LENGTH + 2) // -xxx.xxxxx\0
#define CALC_MAX_INTEGER_SIZE (FP_CALULATOR_TA_MAX_LENGTH)
#define CALC_MAX_DECIMAL_SIZE (FP_CALULATOR_TA_MAX_LENGTH - 2)
#define CALC_MAX_NUM_SIZE (CALC_MAX_INTEGER_SIZE + CALC_MAX_DECIMAL_SIZE) /*xxx.xxx*/
#define CALC_MAX_BUF_SIZE (CALC_MAX_NUM_SIZE + 1) /* integer [0, CALC_MAX_INTEGER_SIZE - 1],
                                                   * decimal [CALC_MAX_INTEGER_SIZE, CALC_MAX_NUM_SIZE - 1],
                                                   * reserved for round [CALC_MAX_NUM_SIZE] */

/**
 * Callback of  warning, auto-back timer
 * param (in) Para: UINT32
 * return VOID:
 */
VOID Calc_Warning_Timeout(VOID* Para)
{
    Nav_Forward(ACT_ID_CALCULATOR_WARNING, ACT_ID_CALCULATOR, NULL, NULL);
}


/**
 * Callback of  warning, on create
 * param (in) pPara: VOID*
 * return VOID:
 */
VOID Calc_Warning_Create(VOID *pPara)
{
    // Create & start 1s auto-back timer
    UINT8 Para = 0;
    TimeId = Hal_Timer_Start(1000, Calc_Warning_Timeout, (VOID *)&Para, FALSE);
}


/**
 * Callback of warning, on destroy
 * param (in) pPara: VOID*, pointer of UI_Status_Desc_t
 * return VOID:
 */
VOID Calc_Warning_Destroy(VOID *pPara)
{
    if (TimeId)
    {
        Hal_Timer_Stop(TimeId);
        TimeId = NULL;
    }
    Hal_Mem_Free(pPara);
}


/**
 * Key function of warning interface
 * param (in) obj: lv_obj_t*
 *       (in) key_sta: UI_KEY_STATUS
 *       (in) key_val: UI_KEY_VALUE
 * return UINT8: 0--call system handling outside
 *               1--handled inside
 */
UINT8 Calc_Warning_KeyCb(lv_obj_t *obj, UI_KEY_STATUS key_sta, UI_KEY_VALUE key_val)
{
    if (KEY_RELEASED != key_sta)
    {
        return(0);
    }

    if (KEY_END == key_val)
    {
        Nav_Home(ACT_ID_ANY);
        return(1);
    }
    else
    {
        return(0);
    }
}


/**
 * Create out of range interface
 * param (in) VOID
 * return VOID:
 */
VOID Calc_Out_Range(VOID)
{
    UI_Status_Desc_t *StatusDesc;
    Nav_Func_List_t  FuncList;

    StatusDesc = (UI_Status_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Status_Desc_t));
    memset(StatusDesc, 0, sizeof(UI_Status_Desc_t));

    StatusDesc->ContLabel.TxtId      = PHONE_TEXT_ID_OUT_RANGE;
    StatusDesc->ContLabel.TxtAlign   = LV_LABEL_ALIGN_LEFT;
    StatusDesc->ContLabel.LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    StatusDesc->ContImg.Img          = LV_SYMBOL_WARNING;
    StatusDesc->ContImg.ImgAlign     = LV_ALIGN_IN_TOP_RIGHT;
    StatusDesc->ContLabelAlign       = LV_ALIGN_IN_TOP_LEFT;

    StatusDesc->KeyFunc = Calc_Warning_KeyCb;

    memset(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow    = UI_Status_Create;
    FuncList.OnCreate  = Calc_Warning_Create;
    FuncList.OnDestroy = Calc_Warning_Destroy;

    Nav_Forward(ACT_ID_CALCULATOR, ACT_ID_CALCULATOR_WARNING, &FuncList, (VOID *)StatusDesc);
}


/**
 * Create cannot divide by zero interface
 * param (in) VOID
 * return VOID:
 */
VOID Calc_Not_Divide_By_Zero(VOID)
{
    UI_Status_Desc_t *StatusDesc;
    Nav_Func_List_t  FuncList;

    StatusDesc = (UI_Status_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Status_Desc_t));
    memset(StatusDesc, 0, sizeof(UI_Status_Desc_t));

    StatusDesc->ContLabel.TxtId      = PHONE_TEXT_ID_NOT_DIVIDE_BY_ZERO;
    StatusDesc->ContLabel.TxtAlign   = LV_LABEL_ALIGN_LEFT;
    StatusDesc->ContLabel.LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    StatusDesc->ContImg.Img          = LV_SYMBOL_WARNING;
    StatusDesc->ContImg.ImgAlign     = LV_ALIGN_IN_TOP_RIGHT;
    StatusDesc->ContLabelAlign       = LV_ALIGN_IN_TOP_LEFT;

    StatusDesc->KeyFunc = Calc_Warning_KeyCb;

    memset(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow    = UI_Status_Create;
    FuncList.OnCreate  = Calc_Warning_Create;
    FuncList.OnDestroy = Calc_Warning_Destroy;

    Nav_Forward(ACT_ID_CALCULATOR, ACT_ID_CALCULATOR_WARNING, &FuncList, (VOID *)StatusDesc);
}


/**
 * Get string from number array
 * param (in) Str: UINT8 *
 * param (in) Negative: BOOL
 * param (out) Result: INT8 *
 * return VOID:
 */
static VOID Calc_Get_Number_String(UINT8 *Str, BOOL Negative, INT8 *Result)
{
    INT16 i;
    UINT8 Start = 0;
    UINT8 End;
    UINT8 Index = 0;

    // Hal_Mem_Set(Result, 0, CALC_MAX_RESULT_LEN);

    for (i = 0; i < CALC_MAX_BUF_SIZE; i++)
    {
        if (Str[i] > 0)
        {
            Start = i;
            break;
        }
    }
    if (i == CALC_MAX_BUF_SIZE)
    {
        Result[0] = '0';
        return;
    }

    if (Start <= 1)
    {
        End = CALC_MAX_INTEGER_SIZE - 1;
    }
    else if (Start < CALC_MAX_INTEGER_SIZE)
    {
        End = CALC_MAX_INTEGER_SIZE + Start - 2;
    }
    else
    {
        End = CALC_MAX_NUM_SIZE - 1;
    }
    if (Str[End + 1] > 4)
    {
        // round
        for (i = End;i >= 0;i--)
        {
            Str[i]++;
            if (Str[i] > 9)
            {
                Str[i] = 0;
            }
            else
            {
                break;
            }
        }
        if (i == -1)
        {
            Calc_Out_Range();
            return;
        }
        if (i < Start)
        {
            Start = i;
        }
    }
    if (End >= CALC_MAX_INTEGER_SIZE)
    {
        for (i = End;i >= CALC_MAX_INTEGER_SIZE;i--)
        {
            if (Str[i] > 0)
            {
                break;
            }
        }
        End = i;
    }
    printf("%s: start %d, end %d, negative %d\n", __FUNCTION__, Start, End, Negative);
    if (Negative)
    {
        Result[Index++] = '-';
    }
    if (Start < CALC_MAX_INTEGER_SIZE)
    {
        for (i = Start;i < CALC_MAX_INTEGER_SIZE;i++)
        {
            Result[Index++] = Str[i] + '0';
        }
        if (End >= CALC_MAX_INTEGER_SIZE)
        {
            Result[Index++] = '.';
            for (i = CALC_MAX_INTEGER_SIZE;i <= End;i++)
            {
                Result[Index++] = Str[i] + '0';
            }
        }
    }
    else
    {
        Result[Index++] = '0';
        Result[Index++] = '.';
        for (i = CALC_MAX_INTEGER_SIZE;i <= End;i++)
        {
            Result[Index++] = Str[i] + '0';
        }
    }
}

/**
 * Copy string into number array
 * param (in) Input: INT8 *
 * param (out) Output: UINT8 *
 * return VOID:
 */
static VOID Calc_Copy_Str_To_Num(INT8 *Input, UINT8 *Output)
{
    UINT8 Len = strlen(Input);
    UINT8 DecPos = Len;
    UINT8 i;
    UINT8 Index;

    for (i = Len - 1; i > 0; i--)
    {
        if (Input[i] == '.')
        {
            DecPos = i;
            break;
        }
    }
    Index = CALC_MAX_INTEGER_SIZE - DecPos;
    for (i = 0; i < DecPos; i++)
    {
        Output[Index++] = Input[i] - '0';
    }
    if (Len > DecPos)
    {
        for (i = DecPos + 1; i < Len; i++)
        {
            Output[Index++] = Input[i] - '0';
        }
    }
}

/**
 * Addtion
 * param (in) Num1: INT8 *
 * param (in) Num2: INT8 *
 * param (in) Negative: BOOL
 * param (out) Result: INT8 *
 * return VOID:
 */
static VOID Calc_Addition(INT8 *Num1, INT8 *Num2, BOOL Negative, INT8 *Result)
{
    UINT8 Str1[CALC_MAX_BUF_SIZE] = {0};
    UINT8 Str2[CALC_MAX_BUF_SIZE] = {0};
    INT16 i;

    if (Result == NULL)
    {
        printf("%s: Result is NULL\n", __FUNCTION__);
        return;
    }

    printf("%s: num1 %s, num2 %s, negative %d\n", __FUNCTION__, Num1, Num2, Negative);

    Calc_Copy_Str_To_Num(Num1, Str1);
    Calc_Copy_Str_To_Num(Num2, Str2);

    for (i = CALC_MAX_BUF_SIZE - 1; i >= 0; i--)
    {
        Str1[i] += Str2[i];
        if(Str1[i] > 9) {
            if (i == 0)
            {
                Calc_Out_Range();
                return;
            }
            Str1[i] -= 10;
            Str1[i - 1] += 1;
        }
    }
    Calc_Get_Number_String(Str1, Negative, Result);
}


/**
 * Subtraction
 * param (in) Num1: INT8 *
 * param (in) Num2: INT8 *
 * param (in) NegativeNum1: BOOL, negative for Num1
 * param (out) Result: INT8 *
 * return VOID:
 */
static VOID Calc_Subtraction(INT8 *Num1, INT8 *Num2, BOOL NegativeNum1, INT8 *Result)
{
    UINT8 Str1[CALC_MAX_BUF_SIZE]   = {0};
    UINT8 Str2[CALC_MAX_BUF_SIZE]   = {0};
    INT8  StrTmp[CALC_MAX_BUF_SIZE] = {0};
    BOOL  Negative                  = FALSE;
    UINT8 One_Or_Zero               = 0;
    INT16 i;

    if (Result == NULL)
    {
        printf("%s: Result is NULL\n", __FUNCTION__);
        return;
    }

    printf("%s: num1 %s, num2 %s, negative %d\n", __FUNCTION__, Num1, Num2, NegativeNum1);

    Calc_Copy_Str_To_Num(Num1, Str1);
    Calc_Copy_Str_To_Num(Num2, Str2);

    for (i = 0; i < CALC_MAX_BUF_SIZE; i++) {
        if (Str1[i] > Str2[i])
        {
            break;
        }
        else if (Str1[i] < Str2[i])
        {
            Hal_Mem_Copy(StrTmp, Str1, CALC_MAX_BUF_SIZE);
            Hal_Mem_Copy(Str1, Str2, CALC_MAX_BUF_SIZE);
            Hal_Mem_Copy(Str2, StrTmp, CALC_MAX_BUF_SIZE);
            Negative = TRUE;
            break;
        }
    }

    for (i = CALC_MAX_BUF_SIZE - 1; i >= 0; i--)
    {
        Str2[i] += One_Or_Zero;
        if (Str1[i] < Str2[i])
        {
            Str1[i] = Str1[i] + 10 - Str2[i];
            One_Or_Zero = 1;
        }
        else
        {
            Str1[i] -= Str2[i];
            One_Or_Zero = 0;
        }
    }
    if (Negative != NegativeNum1)
    {
        Calc_Get_Number_String(Str1, TRUE, Result);
    }
    else
    {
        Calc_Get_Number_String(Str1, FALSE, Result);
    }
}


/**
 * Get the start and end index for number array
 * param (in) Num: UINT8 *, number array
 * param (out) Start: UINT8 *, start index
 * param (out) End: UINT8 *, end index
 * return VOID:
 */
static VOID Calc_Get_Start_End_Index(UINT8 *Num, UINT8 *Start, UINT8 *End)
{
    UINT8 i;

    for (i = 0;i < (CALC_MAX_BUF_SIZE - 1);i++)
    {
        if (Num[i] > 0)
        {
            *Start = i;
            break;
        }
    }
    *End = CALC_MAX_INTEGER_SIZE - 1;
    for (i = CALC_MAX_BUF_SIZE - 2;i >= CALC_MAX_INTEGER_SIZE;i--)
    {
        if (Num[i] > 0)
        {
            *End = i;
            break;
        }
    }
}


/**
 * Multiplication
 * param (in) Num1: INT8 *
 * param (in) Num2: INT8 *
 * param (in) Negative: BOOL
 * param (out) Result: INT8 *
 * return VOID:
 */
static VOID Calc_Multiplication(INT8 *Num1, INT8 *Num2, BOOL Negative, INT8 *Result)
{
    UINT8  Str1[CALC_MAX_BUF_SIZE] = {0};
    UINT8  Str2[CALC_MAX_BUF_SIZE] = {0};
    UINT16 StrRslt[CALC_MAX_NUM_SIZE + CALC_MAX_DECIMAL_SIZE] = {0};
    INT16  i;
    INT16  j;
    INT16  Index;
    UINT8  Start1 = 0;
    UINT8  Start2 = 0;
    UINT8  End1 = 0;
    UINT8  End2 = 0;

    if (Result == NULL)
    {
        printf("%s: Result is NULL\n", __FUNCTION__);
        return;
    }

    Calc_Copy_Str_To_Num(Num1, Str1);
    Calc_Copy_Str_To_Num(Num2, Str2);

    Calc_Get_Start_End_Index(Str1, &Start1, &End1);
    Calc_Get_Start_End_Index(Str2, &Start2, &End2);

    printf("%s:num1 %s,num2 %s,neg %d,sta1 %d,end1 %d,sta2 %d,end2 %d\n",
           __FUNCTION__, Num1, Num2, Negative, Start1, End1, Start2, End2);

    for (i = End2;i >= Start2;i--)
    {
        for (j = End1;j >= Start1;j--)
        {
            Index = i + j + 1 - CALC_MAX_INTEGER_SIZE;
            if (Index < 0)
            {
                printf("%s: out of range, i %d, j %d\n", __FUNCTION__, i, j);
                Calc_Out_Range();
                return;
            }
            StrRslt[Index] += Str2[i] * Str1[j];
            /* printf("%s: StrRslt[%d] %d\n", __FUNCTION__, Index, StrRslt[Index]); */
        }
    }

    Index = End1 + End2 + 1 - CALC_MAX_INTEGER_SIZE;
    for (i = Index;i >= 0;i--)
    {
        if (StrRslt[i] > 9)
        {
            if (i == 0)
            {
                Calc_Out_Range();
                printf("%s: out of range, StrRslt[%d] %d\n", __FUNCTION__, i, StrRslt[i]);
                return;
            }
            StrRslt[i - 1] += StrRslt[i] / 10;
            StrRslt[i]      = StrRslt[i] % 10;
            /* printf("%s: StrRslt[%d] %d, StrRslt[%d] %d\n", */
            /*        __FUNCTION__, i - 1, StrRslt[i - 1], i, StrRslt[i]); */
        }
    }

    Hal_Mem_Set(Str1, 0, CALC_MAX_BUF_SIZE);
    for (i = 0;i <= Index;i++)
    {
        Str1[i] = StrRslt[i];
        /* printf("%s: Str1[%d] %d, StrRslt[%d] %d\n", __FUNCTION__, i, Str1[i], i, StrRslt[i]); */
    }

    Calc_Get_Number_String(Str1, Negative, Result);
}


/**
 * Compare the two number arrays for division
 * param (in) Str1: UINT8 *
 * param (in) Str2: UINT8 *
 * param (in) Str2Len: UINT8,the length of Str2
 * return INT8: 1 if Str1 > Str2, 0 if Str1 == Str2, -1 if Str1 < Str2
 */
static INT8 Calc_Div_Compare(UINT8 *Str1, UINT8 *Str2, UINT8 Str2Len)
{
    UINT8 i;

    for (i = 0;i < Str2Len;i++)
    {
        if (Str1[i] > Str2[i])
        {
            return 1;
        }
        else if (Str1[i] < Str2[i])
        {
            return -1;
        }
    }

    return 0;
}


/**
 * Division
 * param (in) Num1: INT8 *
 * param (in) Num2: INT8 *
 * param (in) Negative: BOOL
 * param (out) Result: INT8 *
 * return VOID:
 */
static VOID Calc_Division(INT8 *Num1, INT8 *Num2, BOOL Negative, INT8 *Result)
{
    UINT8 Str1[CALC_MAX_BUF_SIZE + CALC_MAX_INTEGER_SIZE] = {0};
    UINT8 Str2[CALC_MAX_BUF_SIZE] = {0};
    UINT8 StrRslt[CALC_MAX_BUF_SIZE] = {0};
    INT16 i;
    INT16 j;
    INT16 Index;
    UINT8 Start1 = 0;
    UINT8 Start2 = 0;
    UINT8 End1 = 0;
    UINT8 End2 = 0;
    UINT8 Len2;
    UINT8 LenTmp;
    UINT8 OneOrZero;
    UINT8 EndIndex;
    /* INT8  DecLen2 = 0; */

    if (Result == NULL)
    {
        printf("%s: Result is NULL\n", __FUNCTION__);
        return;
    }

    Calc_Copy_Str_To_Num(Num1, Str1);
    Calc_Copy_Str_To_Num(Num2, Str2);

    Calc_Get_Start_End_Index(Str1, &Start1, &End1);
    Calc_Get_Start_End_Index(Str2, &Start2, &End2);

    Len2 = End2 - Start2 + 1;
    /* DecLen2 = End2 - CALC_MAX_INTEGER_SIZE + 1; */
    /* Index   = Start1 + Len2 - 1 - DecLen2; */
    Index = Start1 - Start2 + CALC_MAX_INTEGER_SIZE - 1;
    EndIndex = Index + CALC_MAX_INTEGER_SIZE;
    if (EndIndex > CALC_MAX_BUF_SIZE)
    {
        EndIndex = CALC_MAX_BUF_SIZE;
    }
    printf("%s:num1 %s,num2 %s,n %d,st1 %d,e1 %d,st2 %d,e2 %d,ei %d\n",
           __FUNCTION__, Num1, Num2, Negative, Start1, End1, Start2, End2, EndIndex);
    LenTmp = Len2;
    while (Index < EndIndex)
    {
        if ((LenTmp == Len2)
            && (Calc_Div_Compare(&Str1[Start1], &Str2[Start2], LenTmp) < 0))
        {
            Index++;
            LenTmp++;
            continue;
        }

        if (Index < 0)
        {
            Calc_Out_Range();
            return;
        }

        // str1 - str2
        OneOrZero = 0;
        for (i = Start1 + LenTmp - 1, j = End2;i >= Start1;i--, j--)
        {
            if (j >= Start2)
            {
                if (Str1[i] < (Str2[j] + OneOrZero))
                {
                    Str1[i] = Str1[i] + 10 - Str2[j] - OneOrZero;
                    OneOrZero = 1;
                }
                else
                {
                    Str1[i] -= Str2[j] + OneOrZero;
                    OneOrZero = 0;
                }
            }
            else
            {
                Str1[i] -= OneOrZero;
            }
        }

        StrRslt[Index]++;

        for (i = Start1;i < (CALC_MAX_BUF_SIZE + Len2);i++)
        {
            if (Str1[i] > 0)
            {
                break;
            }
        }
        if (i != Start1)
        {
            LenTmp = Len2;
            Start1 = i;
            Index  = Start1 - Start2 + CALC_MAX_INTEGER_SIZE - 1;
        }
    }

    Calc_Get_Number_String(StrRslt, Negative, Result);
}

/**
 * Delete unused decimal point and zero
 * param (in) Input: INT8 *
 *       (out) Output: INT8 *,length is CALC_MAX_RESULT_LEN
 * return VOID
 */
static VOID Calc_Delete_Unused_Chars(INT8 *Input, INT8 *Output)
{
    UINT8 Len = strlen(Input);
    UINT8 DecPos = 0;
    UINT8 i;

    if ((Input == NULL) || (Output == NULL))
    {
        printf("%s: Input %p, Output %p\n", __FUNCTION__, Input, Output);
        return;
    }

    Hal_Mem_Set(Output, 0, CALC_MAX_RESULT_LEN);

    for (i = Len - 1;i > 0;i--)
    {
        if (Input[i] == '.')
        {
            DecPos = i;
            break;
        }
    }
    if (DecPos == 0) // not decimal point
    {
        Hal_Mem_Copy(Output, Input, Len);
    }
    else
    {
        for (i = Len - 1;i > DecPos;i--)
        {
            if (Input[i] > '0')
            {
                Hal_Mem_Copy(Output, Input, i + 1);
                break;
            }
        }
        if (i == DecPos)
        {
            Hal_Mem_Copy(Output, Input, i);
        }
        if (strcmp(Output, "-0") == 0)
        {
            Hal_Mem_Copy(Output, "0", 2);
        }
    }
}

/**
 * Calculate
 * param (in) Fac1: INT8* Factor1
 *       (in) Fac2: INT8* Factor2
 *       (in) Oper: INT8* Operator
 *       (out) Result: INT8* calculation
 * return  VOID
 */
static VOID Calc_Get_Result(INT8 *Fac1, INT8 *Fac2, INT8 *Oper, INT8 * Result)
{
    INT8 Fac2Tmp[CALC_MAX_RESULT_LEN] = {0};

    Calc_Delete_Unused_Chars(Fac2, Fac2Tmp);

    Hal_Mem_Set(Result, 0, CALC_MAX_RESULT_LEN);

    if (strcmp(Oper, LV_SYMBOL_PLUS) == 0)
    {
        if (strcmp(Fac1, "0") == 0)
        {
            if (strcmp(Fac2Tmp, "0") == 0)
            {
                Result[0] = '0';
            }
            else
            {
                Hal_Mem_Copy(Result, Fac2Tmp, strlen(Fac2Tmp));
            }
            return;
        }
        else if (strcmp(Fac2Tmp, "0") == 0)
        {
            Hal_Mem_Copy(Result, Fac1, strlen(Fac1));
            return;
        }

        if(Fac1[0] == '-') {
            if(Fac2Tmp[0] == '-') {
                Calc_Addition(&Fac1[1], &Fac2Tmp[1], TRUE, Result);
            } else {
                Calc_Subtraction(&Fac1[1], Fac2Tmp, TRUE, Result);
            }
        } else {
            if(Fac2Tmp[0] == '-') {
                Calc_Subtraction(Fac1, &Fac2Tmp[1], FALSE, Result);
            } else {
                Calc_Addition(Fac1, Fac2Tmp, FALSE, Result);
            }
        }
    }
    else if (strcmp(Oper, LV_SYMBOL_MINUS) == 0)
    {
        if (strcmp(Fac1, Fac2Tmp) == 0)
        {
            Result[0] = '0';
            return;
        }
        else if (strcmp(Fac1, "0") == 0)
        {
            if (Fac2Tmp[0] == '-')
            {
                Hal_Mem_Copy(Result, &Fac2Tmp[1], strlen(Fac2Tmp) - 1);
            }
            else
            {
                Result[0] = '-';
                Hal_Mem_Copy(&Result[1], Fac2Tmp, strlen(Fac2Tmp));
            }
            return;
        }
        else if (strcmp(Fac2Tmp, "0") == 0)
        {
            Hal_Mem_Copy(Result, Fac1, strlen(Fac1));
            return;
        }

        if(Fac1[0] == '-') {
            if(Fac2Tmp[0] == '-') {
                Calc_Subtraction(&Fac1[1], &Fac2Tmp[1], TRUE, Result);
            } else {
                Calc_Addition(&Fac1[1], Fac2Tmp, TRUE, Result);
            }
        } else {
            if(Fac2Tmp[0] == '-') {
                Calc_Addition(Fac1, &Fac2Tmp[1], FALSE, Result);
            } else {
                Calc_Subtraction(Fac1, Fac2Tmp, FALSE, Result);
            }
        }
    }
    else if (strcmp(Oper, LV_SYMBOL_CLOSE) == 0)
    {
        if ((strcmp(Fac1, "0") == 0) || (strcmp(Fac2Tmp, "0") == 0))
        {
            Result[0] = '0';
            return;
        }

        if(Fac1[0] == '-') {
            if(Fac2Tmp[0] == '-') {
                Calc_Multiplication(&Fac1[1], &Fac2Tmp[1], FALSE, Result);
            } else {
                Calc_Multiplication(&Fac1[1], Fac2Tmp, TRUE, Result);
            }
        } else {
            if(Fac2Tmp[0] == '-') {
                Calc_Multiplication(Fac1, &Fac2Tmp[1], TRUE, Result);
            } else {
                Calc_Multiplication(Fac1, Fac2Tmp, FALSE, Result);
            }
        }
    }
    else if (strcmp(Oper, LV_SYMBOL_DIVIDE) == 0)
    {
        if (strcmp(Fac2Tmp, "0") == 0)
        {
            Calc_Not_Divide_By_Zero();
            return;
        }
        else if (strcmp(Fac1, "0") == 0)
        {
            Result[0] = '0';
            return;
        }
        else if (strcmp(Fac2Tmp, "1") == 0)
        {
            Hal_Mem_Copy(Result, Fac1, strlen(Fac1));
            return;
        }
        else if (strcmp(Fac2Tmp, "-1") == 0)
        {
            if (Fac1[0] == '-')
            {
                Hal_Mem_Copy(Result, &Fac1[1], strlen(Fac1) - 1);
            }
            else
            {
                Result[0] = '-';
                Hal_Mem_Copy(&Result[1], Fac1, strlen(Fac1));
            }
        }

        if(Fac1[0] == '-') {
            if(Fac2Tmp[0] == '-') {
                Calc_Division(&Fac1[1], &Fac2Tmp[1], FALSE, Result);
            } else {
                Calc_Division(&Fac1[1], Fac2Tmp, TRUE, Result);
            }
        } else {
            if(Fac2Tmp[0] == '-') {
                Calc_Division(Fac1, &Fac2Tmp[1], TRUE, Result);
            } else {
                Calc_Division(Fac1, Fac2Tmp, FALSE, Result);
            }
        }
    } else {
        printf("%s: wrong oper %s!\n", __FUNCTION__, Oper);
        return;
    }
    printf("%s: Result %s\n", __FUNCTION__, Result);
    return;
} /* Calc_Get_Result */

/**
 * Key Callback Function of Calculator
 * param (in) obj: lv_obj_t*
 *       (in) key_sta: UI_KEY_STATUS
 *       (in) key_val: UI_KEY_VALUE
 * return UINT8: 0--call system handling outside
 *               1--handled inside
 */
UINT8 Calc_KeyCb(lv_obj_t *obj, UI_KEY_STATUS KeySta, UI_KEY_VALUE KeyVal)
{
    UINT8                       Ret        = 0;
    UI_Normal_Calculator_Desc_t *CalcDesc  = NULL;
    INT8                        *InputTxt  = NULL;
    INT8                        *FacTxt    = NULL;
    INT8                        *FacSym    = NULL;
    INT8                        ResultStr[CALC_MAX_RESULT_LEN] = {0};
    INT8                        InputTmp[CALC_MAX_RESULT_LEN]  = {0};
    UINT8                       i;

    if ((KeySta == KEY_LONGPRESS) && (KeyVal != KEY_SOFTRIGHT))
    {
        return(1);
    }

    CalcDesc = (UI_Normal_Calculator_Desc_t *)gp_CalcCurUIDesc;
    InputTxt = (INT8 *)lv_textarea_get_text(CalcDesc->ContTa.TextArea);

    switch (KeyVal)
    {
    case KEY_UP:
    case KEY_DOWN:
    case KEY_LEFT:
    case KEY_RIGHT:
    {
        if (FALSE == Flag)
        {
            if (InputTxt && strlen(InputTxt) > 0)
            {
                FacTxt = lv_label_get_text(CalcDesc->FactorLabel2.Label);
                if (strlen(FacTxt))
                {
                    FacSym = lv_label_get_text(CalcDesc->SymbolLabel1.Label);
                    Calc_Get_Result(FacTxt, InputTxt, FacSym, ResultStr);
                    if (strlen(ResultStr) > 0)
                    {
                        lv_label_set_text(CalcDesc->FactorLabel2.Label, ResultStr);
                    }
                    else
                    {
                        // out of range or cannot divide by zero
                        return(1);
                    }
                }
                else
                {
                    if (strcmp(InputTxt, "0") == 0)
                    {
                        CalcDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_CLEAR;
                        lv_label_set_text_id(lv_obj_get_child(CalcDesc->ButtonBar.ButtonR.Button,
                                                              NULL),PHONE_TEXT_ID_CLEAR);
                    }

                    // delete unused decimal point and zero
                    Calc_Delete_Unused_Chars(InputTxt, InputTmp);
                    lv_label_set_text(CalcDesc->FactorLabel2.Label, InputTmp);
                }
                lv_textarea_set_text(CalcDesc->ContTa.TextArea, "");
                lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);
            }
        }
        else
        {
            lv_label_set_text(CalcDesc->FactorLabel2.Label,InputTxt);
            lv_textarea_set_text(CalcDesc->ContTa.TextArea, "");
            lv_label_set_text(CalcDesc->FactorLabel1.Label,"");
            lv_label_set_text(CalcDesc->SymbolLabel2.Label,"");
            lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);
            Flag = FALSE;
        }
        if (KeyVal == KEY_UP)
        {
            lv_label_set_text(CalcDesc->SymbolLabel1.Label,LV_SYMBOL_PLUS);
        }
        else if (KeyVal == KEY_DOWN)
        {
            lv_label_set_text(CalcDesc->SymbolLabel1.Label,LV_SYMBOL_MINUS);
        }
        else if (KeyVal == KEY_LEFT)
        {
            lv_label_set_text(CalcDesc->SymbolLabel1.Label,LV_SYMBOL_CLOSE);
        }
        else
        {
            lv_label_set_text(CalcDesc->SymbolLabel1.Label,LV_SYMBOL_DIVIDE);
        }

        Ret = 1;
        break;
    }

    case KEY_OK:
    {
        FacTxt = lv_label_get_text(CalcDesc->FactorLabel2.Label);
        UI_Log_Out(UI_SUB_MODULE_CALCULATOR, UI_LOG_LEVEL_TRACE_3, "FacTxt = %s\n",FacTxt);
        FacSym = lv_label_get_text(CalcDesc->SymbolLabel1.Label);
        if (strlen(InputTxt) && strlen(FacTxt) && !Flag)
        {
            Calc_Get_Result(FacTxt, InputTxt, FacSym, ResultStr);
            if (strlen(ResultStr) > 0)
            {
                lv_label_set_text(CalcDesc->FactorLabel1.Label, FacTxt);
                Calc_Delete_Unused_Chars(InputTxt, InputTmp);
                lv_label_set_text(CalcDesc->FactorLabel2.Label, InputTmp);
                lv_label_set_text(CalcDesc->SymbolLabel2.Label, LV_SYMBOL_EQUALS);
                if (ResultStr[0] == '-')
                {
                    lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH + 1);
                }
                else
                {
                    lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);
                }
                lv_textarea_set_text(CalcDesc->ContTa.TextArea, ResultStr);
                Flag = TRUE;
            }
        }
        Ret = 1;
        break;
    }

    case KEY_SOFTRIGHT:
    {
        if (KeySta == KEY_LONGPRESS)
        {
            LongPressClear = TRUE;
            lv_label_set_text(CalcDesc->FactorLabel1.Label, "");
            lv_label_set_text(CalcDesc->FactorLabel2.Label, "");
            lv_label_set_text(CalcDesc->SymbolLabel1.Label, "");
            lv_label_set_text(CalcDesc->SymbolLabel2.Label, "");
            lv_textarea_set_text(CalcDesc->ContTa.TextArea, "0");
            CalcDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
            lv_label_set_text_id(lv_obj_get_child(CalcDesc->ButtonBar.ButtonR.Button,
                                                  NULL),PHONE_TEXT_ID_BACK);
            lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);
            Flag = FALSE;
            return(1);
        }
        else if ((KeySta == KEY_RELEASED) && LongPressClear)
        {
            LongPressClear = FALSE;
            return(1);
        }

        UINT8 Len = strlen(InputTxt);
        if (Flag)
        {
            lv_label_set_text(CalcDesc->FactorLabel1.Label, "");
            lv_label_set_text(CalcDesc->FactorLabel2.Label, "");
            lv_label_set_text(CalcDesc->SymbolLabel1.Label, "");
            lv_label_set_text(CalcDesc->SymbolLabel2.Label, "");
            lv_textarea_set_text(CalcDesc->ContTa.TextArea, "0");
            lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);
            Flag = FALSE;
            CalcDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
            lv_label_set_text_id(lv_obj_get_child(CalcDesc->ButtonBar.ButtonR.Button,
                                                  NULL),PHONE_TEXT_ID_BACK);
        }
        else if (Len == 0)
        {
            FacTxt = lv_label_get_text(CalcDesc->FactorLabel2.Label);
            if (FacTxt[0] == '-')
            {
                lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH + 1);
            }
            else
            {
                lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);
            }
            lv_textarea_set_text(CalcDesc->ContTa.TextArea, FacTxt);
            if (strcmp(FacTxt, "0") == 0)
            {
                CalcDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
                lv_label_set_text_id(lv_obj_get_child(CalcDesc->ButtonBar.ButtonR.Button,
                                                      NULL),PHONE_TEXT_ID_BACK);
            }
            lv_label_set_text(CalcDesc->FactorLabel2.Label, "");
            lv_label_set_text(CalcDesc->SymbolLabel1.Label, "");
        }
        else if (strcmp(InputTxt, "0") != 0)
        {
            if (Len == 1)
            {
                if (strlen(lv_label_get_text(CalcDesc->FactorLabel2.Label)) > 0)
                {
                    lv_textarea_set_text(CalcDesc->ContTa.TextArea, "");
                }
                else
                {
                    lv_textarea_set_text(CalcDesc->ContTa.TextArea, "0");
                    CalcDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
                    lv_label_set_text_id(lv_obj_get_child(CalcDesc->ButtonBar.ButtonR.Button,
                                                          NULL),PHONE_TEXT_ID_BACK);
                }
            }
            else if ((Len == 2) && (InputTxt[0] == '-'))
            {
                if (strlen(lv_label_get_text(CalcDesc->FactorLabel2.Label)) > 0)
                {
                    lv_textarea_set_text(CalcDesc->ContTa.TextArea, "");
                }
                else
                {
                    lv_textarea_set_text(CalcDesc->ContTa.TextArea, "0");
                    CalcDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
                    lv_label_set_text_id(lv_obj_get_child(CalcDesc->ButtonBar.ButtonR.Button,
                                                          NULL),PHONE_TEXT_ID_BACK);
                }
                lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);
            }
            else if (strcmp(InputTxt, "-0.") == 0)
            {
                lv_textarea_set_text(CalcDesc->ContTa.TextArea, "0");
                CalcDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
                lv_label_set_text_id(lv_obj_get_child(CalcDesc->ButtonBar.ButtonR.Button,
                                                      NULL),PHONE_TEXT_ID_BACK);
                lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);
            }
            else
            {
                lv_textarea_del_char(CalcDesc->ContTa.TextArea);
            }
        }
        else
        {
            FacTxt = lv_label_get_text(CalcDesc->FactorLabel2.Label);
            if (strlen(FacTxt) == 0)
            {
                Nav_Back(ACT_ID_ANY);
            }
            else
            {
                lv_textarea_del_char(CalcDesc->ContTa.TextArea);
            }
        }

        Ret = 1;
        break;
    }

    case KEY_END:
    {
        Flag = FALSE;
        Nav_Home(ACT_ID_ANY);
        Ret = 1;
        break;
    }

    case KEY_1:
    case KEY_2:
    case KEY_3:
    case KEY_4:
    case KEY_5:
    case KEY_6:
    case KEY_7:
    case KEY_8:
    case KEY_9:
    {
        if (Flag)
        {
            lv_label_set_text(CalcDesc->FactorLabel1.Label, "");
            lv_label_set_text(CalcDesc->FactorLabel2.Label, "");
            lv_label_set_text(CalcDesc->SymbolLabel1.Label, "");
            lv_label_set_text(CalcDesc->SymbolLabel2.Label, "");
            lv_textarea_set_text(CalcDesc->ContTa.TextArea, "");
            lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);
            Flag = FALSE;
        }
        else if (strcmp(InputTxt, "0") == 0)
        {
            lv_textarea_set_text(CalcDesc->ContTa.TextArea,"");
        }
        CalcDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_CLEAR;
        lv_label_set_text_id(lv_obj_get_child(CalcDesc->ButtonBar.ButtonR.Button,
                NULL),PHONE_TEXT_ID_CLEAR);
        break;
    }

    case KEY_0:
        if (Flag)
        {
            lv_label_set_text(CalcDesc->FactorLabel1.Label, "");
            lv_label_set_text(CalcDesc->FactorLabel2.Label, "");
            lv_label_set_text(CalcDesc->SymbolLabel1.Label, "");
            lv_label_set_text(CalcDesc->SymbolLabel2.Label, "");
            lv_textarea_set_text(CalcDesc->ContTa.TextArea, "0");
            CalcDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
            lv_label_set_text_id(lv_obj_get_child(CalcDesc->ButtonBar.ButtonR.Button,
                                                  NULL),PHONE_TEXT_ID_BACK);
            lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);
            Flag = FALSE;
        }
        else if (strcmp(InputTxt, "0") != 0)
        {
            lv_textarea_add_char(CalcDesc->ContTa.TextArea, '0');
        }
        Ret = 1;
        break;

    case KEY_HASH: // '.'
    {
        if (Flag)
        {
            Flag = FALSE;

            lv_label_set_text(CalcDesc->FactorLabel1.Label, "");
            lv_label_set_text(CalcDesc->FactorLabel2.Label, "");
            lv_label_set_text(CalcDesc->SymbolLabel1.Label, "");
            lv_label_set_text(CalcDesc->SymbolLabel2.Label, "");
            lv_textarea_set_text(CalcDesc->ContTa.TextArea, "0.");
            lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);
        }
        else if ((strlen(InputTxt) == 0) || (strcmp(InputTxt, "0") == 0))
        {
            lv_textarea_set_text(CalcDesc->ContTa.TextArea,"0.");
            CalcDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_CLEAR;
            lv_label_set_text_id(lv_obj_get_child(CalcDesc->ButtonBar.ButtonR.Button,
                                                  NULL),PHONE_TEXT_ID_CLEAR);
        }
        else
        {
            for (i = 0;InputTxt[i] != '\0';i++)
            {
                if (InputTxt[i] == '.')
                {
                    break;
                }
            }
            if (InputTxt[i] == '\0')
            {
                lv_textarea_add_text(CalcDesc->ContTa.TextArea,".");
            }
        }
        Ret = 1;
        break;
    }

    case KEY_ASTERISK: // '-'
    {
        if ((strlen(InputTxt) != 0) && (strcmp(InputTxt, "0") != 0))
        {
            INT8 p[FP_CALULATOR_TA_MAX_LENGTH + 2] = { 0 };
            if (InputTxt[0] == '-')
            {
                strcat(p, &InputTxt[1]);
                lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);
            }
            else
            {
                p[0] = '-';
                strcat(p,InputTxt);
                lv_textarea_set_max_length(CalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH + 1);
            }
            lv_textarea_set_text(CalcDesc->ContTa.TextArea, p);
        }
        Ret = 1;
        break;
    }

    default:
        break;
    } /* switch */

    return(Ret);
} /* Calc_KeyCb */


/**
 *
 * Callback of Calculatot on destroy
 * param (in) UI_Normal_Calculator_Desc_t*
 * return VOID:
 */
VOID Calc_OnDestroy(VOID *pPara)
{
    UI_Normal_Calculator_Desc_t *pCalcDesc = NULL;

    pCalcDesc = (UI_Normal_Calculator_Desc_t *)pPara;
    Hal_Mem_Free(pCalcDesc);
    Hal_Mem_Free(gs_CalcOperState.Fac1);
    Hal_Mem_Free(gs_CalcOperState.Fac2);
    Hal_Mem_Free(gs_CalcOperState.Oper1);
    Hal_Mem_Free(gs_CalcOperState.Oper2);
    Hal_Mem_Free(gs_CalcOperState.Res);
    memset(&gs_CalcOperState, 0, sizeof(Calc_Operate_State));
}


/**
 *
 * Callback of Calculatot on create
 * param (in) UI_Normal_Calculator_Desc_t*
 * return VOID:
 */
VOID Calc_OnCreate(VOID *pPara)
{
    UI_Normal_Calculator_Desc_t *pCalcDesc = (UI_Normal_Calculator_Desc_t *)pPara;

    lv_textarea_set_max_length(pCalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);

    memset(&gs_CalcOperState, 0, sizeof(Calc_Operate_State));
    gs_CalcOperState.Fac1  = Hal_Mem_Alloc(CALC_MAX_RESULT_LEN);
    gs_CalcOperState.Fac2  = Hal_Mem_Alloc(CALC_MAX_RESULT_LEN);
    gs_CalcOperState.Oper1 = Hal_Mem_Alloc(2);
    gs_CalcOperState.Oper2 = Hal_Mem_Alloc(2);
    gs_CalcOperState.Res   = Hal_Mem_Alloc(CALC_MAX_RESULT_LEN);

    Flag           = FALSE;
    LongPressClear = FALSE;
}


/**
 *
 * Callback of Calculatot on save
 * param (in) UI_Normal_Calculator_Desc_t*
 * return VOID:
 */
VOID Calc_OnSave(VOID *pPara)
{
    UI_Normal_Calculator_Desc_t *pCalcDesc = (UI_Normal_Calculator_Desc_t *)gp_CalcCurUIDesc;
    const INT8 *Fac1 = lv_label_get_text(pCalcDesc->FactorLabel1.Label);
    const INT8 *Fac2 = lv_label_get_text(pCalcDesc->FactorLabel2.Label);
    const INT8 *Oper1 = lv_label_get_text(pCalcDesc->SymbolLabel1.Label);
    const INT8 *Oper2 = lv_label_get_text(pCalcDesc->SymbolLabel2.Label);
    const INT8 *Res = lv_textarea_get_text(pCalcDesc->ContTa.TextArea);

    Hal_Mem_Copy(gs_CalcOperState.Fac1, Fac1, strlen(Fac1) + 1);
    Hal_Mem_Copy(gs_CalcOperState.Fac2, Fac2, strlen(Fac2) + 1);
    Hal_Mem_Copy(gs_CalcOperState.Oper1, Oper1, strlen(Oper1) + 1);
    Hal_Mem_Copy(gs_CalcOperState.Oper2, Oper2, strlen(Oper2) + 1);
    Hal_Mem_Copy(gs_CalcOperState.Res, Res, strlen(Res) + 1);
}


/**
 *
 * Callback of Calculatot on restore
 * param (in) UI_Normal_Calculator_Desc_t*
 * return VOID:
 */
VOID Calc_OnRestore(VOID *pPara)
{
    UI_Normal_Calculator_Desc_t *pCalcDesc = (UI_Normal_Calculator_Desc_t *)gp_CalcCurUIDesc;

    if (gs_CalcOperState.Res[0] == '-')
    {
        lv_textarea_set_max_length(pCalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH + 1);
    }
    else
    {
        lv_textarea_set_max_length(pCalcDesc->ContTa.TextArea, FP_CALULATOR_TA_MAX_LENGTH);
    }

    lv_label_set_text(pCalcDesc->FactorLabel1.Label, gs_CalcOperState.Fac1);
    lv_label_set_text(pCalcDesc->FactorLabel2.Label, gs_CalcOperState.Fac2);
    lv_label_set_text(pCalcDesc->SymbolLabel1.Label, gs_CalcOperState.Oper1);
    lv_label_set_text(pCalcDesc->SymbolLabel2.Label, gs_CalcOperState.Oper2);
    lv_textarea_set_text(pCalcDesc->ContTa.TextArea, gs_CalcOperState.Res);
}


/**
 * Calculator APP main entrance
 * param (in) void
 * return  void
 */
VOID Calc_Main(VOID)
{
    printf("Calculator APP\n");

    UI_Normal_Calculator_Desc_t *CalcDesc = NULL;
    Nav_Func_List_t             FuncList;
    CalcDesc = (UI_Normal_Calculator_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_Calculator_Desc_t));

    memset(CalcDesc, 0, sizeof(UI_Normal_Calculator_Desc_t));
    CalcDesc->FactorLabel1.TxtId    = LV_LANG_TXT_ID_NONE;
    CalcDesc->FactorLabel1.TxtAlign = LV_LABEL_ALIGN_RIGHT;
    CalcDesc->FactorLabel1.TxtFont  = LV_THEME_SIMPLE_FONT_SMALL;

    CalcDesc->FactorLabel2.TxtId    = LV_LANG_TXT_ID_NONE;
    CalcDesc->FactorLabel2.TxtAlign = LV_LABEL_ALIGN_RIGHT;
    CalcDesc->FactorLabel2.TxtFont  = LV_THEME_SIMPLE_FONT_SMALL;

    CalcDesc->SymbolLabel1.TxtId   = LV_LANG_TXT_ID_NONE;
    CalcDesc->SymbolLabel1.TxtFont = LV_FONT_PTR_DRIODSANSFALLBACKFULL_SMALL;
    CalcDesc->SymbolLabel2.TxtId   = LV_LANG_TXT_ID_NONE;
    CalcDesc->SymbolLabel2.TxtFont = LV_FONT_PTR_DRIODSANSFALLBACKFULL_SMALL;

    CalcDesc->ContTa.TaCursorHide = TRUE;
    CalcDesc->ContTa.TaAlign      = LV_LABEL_ALIGN_RIGHT;

    CalcDesc->ContLabel.ContLabelU.TxtId = LV_LANG_TXT_ID_NONE;
    CalcDesc->ContLabel.ContLabelL.TxtId = LV_LANG_TXT_ID_NONE;
    CalcDesc->ContLabel.ContLabelR.TxtId = LV_LANG_TXT_ID_NONE;
    CalcDesc->ContLabel.ContLabelD.TxtId = LV_LANG_TXT_ID_NONE;

    CalcDesc->ContLabel.ContLabelU.SymbolAlign = LV_LABEL_ALIGN_CENTER;
    CalcDesc->ContLabel.ContLabelL.SymbolAlign = LV_LABEL_ALIGN_CENTER;
    CalcDesc->ContLabel.ContLabelR.SymbolAlign = LV_LABEL_ALIGN_CENTER;
    CalcDesc->ContLabel.ContLabelD.SymbolAlign = LV_LABEL_ALIGN_CENTER;

    CalcDesc->ContLabel.ContLabelU.TxtFont  = LV_FONT_PTR_DRIODSANSFALLBACKFULL_SMALL;
    CalcDesc->ContLabel.ContLabelU.SymbolId = LV_SYMBOL_PLUS;
    CalcDesc->ContLabel.ContLabelL.TxtFont  = LV_FONT_PTR_DRIODSANSFALLBACKFULL_SMALL;
    CalcDesc->ContLabel.ContLabelL.SymbolId = LV_SYMBOL_CLOSE;
    CalcDesc->ContLabel.ContLabelR.TxtFont  = LV_FONT_PTR_DRIODSANSFALLBACKFULL_SMALL;
    CalcDesc->ContLabel.ContLabelR.SymbolId = LV_SYMBOL_DIVIDE;
    CalcDesc->ContLabel.ContLabelD.TxtFont  = LV_FONT_PTR_DRIODSANSFALLBACKFULL_SMALL;
    CalcDesc->ContLabel.ContLabelD.SymbolId = LV_SYMBOL_MINUS;

    CalcDesc->ButtonBar.ButtonL.Valid = FALSE;
    CalcDesc->ButtonBar.ButtonM.Valid = TRUE;
    CalcDesc->ButtonBar.ButtonR.Valid = TRUE;

    CalcDesc->ButtonBar.ButtonM.TxtId = PHONE_TEXT_ID_EQUALS;
    CalcDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
    CalcDesc->KeyFunc                 = Calc_KeyCb;

    memset(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Normal_Calculator_Create;
    FuncList.OnCreate       = Calc_OnCreate;
    FuncList.OnDestroy      = Calc_OnDestroy;
    FuncList.OnSaveState    = Calc_OnSave;
    FuncList.OnRestoreState = Calc_OnRestore;

    gp_CalcCurUIDesc = (VOID *)CalcDesc;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CALCULATOR, &FuncList, (VOID *)CalcDesc);
} /* Calc_Main */


/**
 * Initiate calendar module
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Calculator_Init_Req(VOID)
{
    If_Framework_Reg_Info_t *RegInfo;

    RegInfo             = (If_Framework_Reg_Info_t *)Hal_Mem_Alloc(sizeof(If_Framework_Reg_Info_t));
    RegInfo->NameTextId = PHONE_TEXT_ID_CALCULATOR;
    RegInfo->AppImage   = IMG_MENU_CALCULATOR;
    RegInfo->AppFunc    = Calc_Main;
    Framework_App_Register_Req(RegInfo);
}
